#include <vector>
#include <string>
#include <iostream>
using namespace std;
namespace M_M_Map{
    typedef struct {
        int row;
        int col;
    }m_position;
    typedef enum{
        m_e_empty   =   0,
        m_e_block   =   1,
        m_e_visited =   2,
        m_e_path    =   3,
        m_e_start   =   4,
        m_e_end     =   5,
        m_e_trajectory= 6
    }mitrix_block;
    typedef enum{
        e_move_up   =   0,
        e_move_down =   1,
        e_move_left =   2,
        e_move_right=   3
    }e_mitrix_move;
    class Mitrix_M_Map
    {
    private:
        /* data */
        int** mitrix_M_Map;
        int length;
        int height;
    public:
        m_position** generateParentM_Map(){
            m_position** parents=new m_position*[height];
            for(int i=0;i<height;i++){
                parents[i]=new m_position[length];
                for(int j=0;j<length;j++){
                    parents[i][j]={-1,-1};
                }
            }
            return parents;
        }
        int getLength(){
            return this->length;
        }
        int getHeight(){
            return this->height;
        }
        Mitrix_M_Map(/* args */int len,int height);
        ~Mitrix_M_Map();
        void addBlock(int row,int col);
        void addBlock(m_position p);
        //判断位置是否越界
        bool isValid(m_position p);
        void print();
        bool isVisited(m_position p){
            if(mitrix_M_Map[p.row][p.col]!=m_e_empty&&mitrix_M_Map[p.row][p.col]!=m_e_end)
                return true;
            return false;
        }
        void setTrajectory(m_position p){
            mitrix_M_Map[p.row][p.col]=m_e_trajectory;
        }
        void setVisit(m_position p){
            mitrix_M_Map[p.row][p.col]=m_e_visited;
        }
        void setPath(m_position p){
            mitrix_M_Map[p.row][p.col]=m_e_path;
        }
        void setStart(m_position p){
            mitrix_M_Map[p.row][p.col]=m_e_start;
        }
        void setEnd(m_position p){
            mitrix_M_Map[p.row][p.col]=m_e_end;
        }
        m_position move(m_position p, e_mitrix_move m);
    };
    Mitrix_M_Map::Mitrix_M_Map(/* args */int len,int height)
    {
        this->length=len;
        this->height=height;
        mitrix_M_Map=new int*[height];
        for(int i=0;i<height;i++){
            mitrix_M_Map[i]=new int[len];
            for(int j=0;j<len;j++){
                mitrix_M_Map[i][j]=m_e_empty;
            }
        }
    }
    
    Mitrix_M_Map::~Mitrix_M_Map()
    {

    }
    void Mitrix_M_Map::addBlock(int row,int col){
        mitrix_M_Map[row][col]=m_e_block;
    }
    void Mitrix_M_Map::addBlock(m_position p){
        mitrix_M_Map[p.row][p.col]=m_e_block;
    }
    bool Mitrix_M_Map::isValid(m_position p){
        if (p.row>=height||p.row<0)
        {
            return false;
        }
        if(p.col>=length||p.col<0){
            return false;
        }
        //block位置视为越界
        if(mitrix_M_Map[p.row][p.col]==m_e_block){
            return false;
        }
        return true;
    }

    void Mitrix_M_Map:: print(){
        for (int i = 0; i < height; i++)
        {
            for(int j=0;j<length;j++){
                switch (mitrix_M_Map[i][j])
                {
                case m_e_empty:
                    /* code */
                    cout<<"."<<" ";
                    break;
                case m_e_block:
                    cout<<"#"<<" ";
                    break;
                case m_e_visited:
                    cout<<"-"<<" ";
                    break;
                case m_e_path:
                    cout<<"@"<<" ";
                    break;
                case m_e_start:
                    cout<<"S"<<" ";
                    break;
                case m_e_end:
                    cout<<"E"<<" ";
                    break;
                case m_e_trajectory:
                    cout<<"T"<<" ";
                default:
                    break;
                }
            }
            cout<<endl;
        }
    }
    m_position Mitrix_M_Map::move(m_position p,e_mitrix_move m){
        m_position result=p;
        switch (m)
        {
        case e_move_up:
            /* code */
            result.row=p.row-1;
            break;
        case e_move_down:
            result.row=p.row+1;
            break;
        case e_move_left:
            result.col=result.col-1;
            break;
        case e_move_right:
            result.col=result.col+1;
            break;
        default:
            break;
        }
        return result;
    }
}